﻿// BusinessLicenseService.cs（服务层实现）
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using MySqlConnector;
using SimpleWebApi.Business.Service.Interface.DTO.BusinessLicenseDTO;
using SimpleWebApi.Business.Service.Interface.IBusinessLicense;
using SimpleWebApi.MyMigration.Models;
using SimpleWebApi.MyMigration.Models.BusinessLicenseManagement;
using static SimpleWebApi.MyMigration.AdvancedCustomerDbContext;

namespace SimpleWebApi.Business.Service.BusinessLicenseSer
{
    public class BusinessLicenseService : BaseService, IBusinessLicenseService
    {
        private readonly IMapper _mapper;

        public BusinessLicenseService(DbContext context, IMapper mapper) : base(context)
        {
            _mapper = mapper;
        }

        public async Task<BusinessLicense> CreateBusinessLicenseAsync(BusinessLicenseCreateDto dto)
        {
            // 参数校验
            if (dto.LegalPersonId == null && dto.LegalPersonCreate == null)
                throw new ArgumentException("必须提供法人信息");

            using var transaction = await Context.Database.BeginTransactionAsync();
            try
            {
                // 处理法人（更新或新建）
                var legalPerson = await ProcessLegalPersonAsync(dto);
                await Context.SaveChangesAsync(); // 先保存法人

                // 创建营业执照主体
                var license = _mapper.Map<BusinessLicense>(dto);
                license.LegalPerson = legalPerson;
                Context.Set<BusinessLicense>().Add(license);
                await Context.SaveChangesAsync(); // 再保存营业执照

                // 处理关联人（如果存在）
                if (dto.RelatedPersons?.Any() == true)
                {
                    await ProcessRelatedPersonsAsync(license, dto.RelatedPersons);
                    await Context.SaveChangesAsync(); // 最后保存关联人和中间表
                }

                await transaction.CommitAsync();
                return license;
            }
            catch (DbUpdateException ex) when (IsUniqueConstraintViolation(ex))
            {
                throw new InvalidOperationException("身份证号已存在", ex);
            }
            catch
            {
                await transaction.RollbackAsync();
                throw;
            }
        }

        public async Task<BusinessLicense> UpdateBusinessLicenseAsync(BusinessLicenseUpdateDto dto)
        {
            // 参数校验
            if (dto.LicenseId <= 0)
                throw new ArgumentException("无效的执照ID");

            using var transaction = await Context.Database.BeginTransactionAsync();
            try
            {
                // 1. 获取待更新的执照（包含关联数据）
                var license = await Context.Set<BusinessLicense>()
                    .Include(bl => bl.LegalPerson)
                    .Include(bl => bl.RelatedPersons)
                        .ThenInclude(rp => rp.RelatedPerson)
                    .FirstOrDefaultAsync(bl => bl.Id == dto.LicenseId);

                if (license == null)
                    throw new ArgumentException("执照不存在");

                // 2. 更新基础信息（仅更新非空字段）
                _mapper.Map(dto, license);  // 使用 AutoMapper 配置忽略空值

                // 3. 处理法人变更（可选）
                await ProcessLegalPersonUpdateAsync(license, dto);

                // 4. 处理关联人操作（添加/更新/删除）
                await ProcessRelatedPersonOperationsAsync(license, dto.RelatedPersonOperations);

                // 5. 保存变更
                await Context.SaveChangesAsync();
                await transaction.CommitAsync();

                return license;
            }
            catch (DbUpdateException ex) when (IsUniqueConstraintViolation(ex))
            {
                throw new InvalidOperationException("数据唯一性冲突（如身份证号重复）", ex);
            }
            catch
            {
                await transaction.RollbackAsync();
                throw;
            }
        }

        public async Task<PagedResult<BusinessLicense>> SearchLicensesAsync(BusinessLicenseQueryDto queryDto)
        {
            // 构建基础查询（包含法人信息）
            var query = Context.Set<BusinessLicense>()
                .Include(bl => bl.LegalPerson)
                .AsQueryable();

            // 动态添加筛选条件
            if (!string.IsNullOrEmpty(queryDto.TradeName))
            {
                query = query.Where(bl => bl.TradeName.Contains(queryDto.TradeName));
            }

            if (!string.IsNullOrEmpty(queryDto.CreditCode))
            {
                query = query.Where(bl => bl.CreditCode == queryDto.CreditCode); // 精确匹配信用代码
            }

            if (!string.IsNullOrEmpty(queryDto.LegalPersonName))
            {
                query = query.Where(bl => bl.LegalPerson.Name.Contains(queryDto.LegalPersonName));
            }

            // 计算总数
            int totalCount = await query.CountAsync();

            // 分页并执行查询
            var items = await query
                .OrderBy(bl => bl.Id)
                .Skip((queryDto.PageNumber - 1) * queryDto.PageSize)
                .Take(queryDto.PageSize)
                .AsNoTracking()
                .ToListAsync();

            return new PagedResult<BusinessLicense>
            {
                Total = totalCount,
                PageNumber = queryDto.PageNumber,
                PageSize = queryDto.PageSize,
                Items = items
            };
        }

        /// <summary>
        /// 处理法人变更（更换法人或更新信息）
        /// </summary>
        private async Task ProcessLegalPersonUpdateAsync(BusinessLicense license, BusinessLicenseUpdateDto dto)
        {
            // 情况1：更换法人（指定新LegalPersonId）
            if (dto.LegalPersonId.HasValue)
            {
                var newLegalPerson = await Context.Set<LegalPerson>().FindAsync(dto.LegalPersonId.Value);
                if (newLegalPerson == null)
                    throw new ArgumentException("新法人不存在");

                license.LegalPerson = newLegalPerson;  // 直接更换法人
                return;
            }

            // 情况2：更新当前法人信息（需提供LegalPersonUpdate）
            if (dto.LegalPersonUpdate != null)
            {
                // 合并更新数据
                _mapper.Map(dto.LegalPersonUpdate, license.LegalPerson);

                // 校验身份证号唯一性（如果修改了）
                if (!string.IsNullOrEmpty(dto.LegalPersonUpdate.IdNumber) &&
                    license.LegalPerson.IdNumber != dto.LegalPersonUpdate.IdNumber)
                {
                    bool exists = await Context.Set<LegalPerson>()
                        .AnyAsync(lp => lp.IdNumber == dto.LegalPersonUpdate.IdNumber);
                    if (exists) throw new InvalidOperationException("法人身份证号已存在");
                }
            }
        }

        /// <summary>
        /// 处理关联人操作（添加/更新/删除）
        /// </summary>
        private async Task ProcessRelatedPersonOperationsAsync(
            BusinessLicense license,
            List<RelatedPersonOperationDto>? operations)
        {
            if (operations == null || !operations.Any()) return;

            foreach (var operation in operations)
            {
                // 删除关联人（提供ID且UpdateData为空）
                if (operation.RelatedPersonId.HasValue && operation.UpdateData == null)
                {
                    var relation = license.RelatedPersons
                        .FirstOrDefault(rp => rp.RelatedPersonId == operation.RelatedPersonId);
                    if (relation != null)
                        license.RelatedPersons.Remove(relation);
                }
                // 更新关联人信息（提供ID和UpdateData）
                else if (operation.RelatedPersonId.HasValue && operation.UpdateData != null)
                {
                    var relatedPerson = await Context.Set<RelatedPerson>()
                        .FindAsync(operation.RelatedPersonId.Value);
                    if (relatedPerson == null)
                        throw new ArgumentException($"关联人ID {operation.RelatedPersonId} 不存在");

                    // 合并更新数据
                    _mapper.Map(operation.UpdateData, relatedPerson);

                    // 校验身份证号唯一性
                    if (!string.IsNullOrEmpty(operation.UpdateData.IdNumber) &&
                        relatedPerson.IdNumber != operation.UpdateData.IdNumber)
                    {
                        bool exists = await Context.Set<RelatedPerson>()
                            .AnyAsync(rp => rp.IdNumber == operation.UpdateData.IdNumber);
                        if (exists) throw new InvalidOperationException("关联人身份证号已存在");
                    }
                }
                // 新增关联人（不提供ID，但需提供UpdateData）
                else if (operation.UpdateData != null)
                {
                    var newPerson = _mapper.Map<RelatedPerson>(operation.UpdateData);
                    Context.Set<RelatedPerson>().Add(newPerson);
                    license.RelatedPersons.Add(new BusinessLicenseRelatedPerson
                    {
                        BusinessLicense = license,
                        RelatedPerson = newPerson
                    });
                }
                else
                {
                    throw new ArgumentException("关联人操作不完整");
                }
            }
        }

        public async Task<BusinessLicense?> GetLicenseByIdAsync(int id)
        {
            // 参数校验：确保ID合法
            if (id <= 0)
            {
                throw new ArgumentException("ID必须是正整数", nameof(id));
            }

            // 使用EF Core查询，包含导航属性
            var license = await Context.Set<BusinessLicense>()
                .AsNoTracking() // 禁用跟踪，提高查询性能
                .Include(bl => bl.LegalPerson) // 加载法人信息
                    .ThenInclude(lp => lp.BusinessLicenses) // 加载法人关联的营业执照（按需）
                .Include(bl => bl.RelatedPersons) // 加载中间表
                    .ThenInclude(blr => blr.RelatedPerson) // 加载关联人详细信息
                .Where(bl => bl.Id == id && !bl.IsDeleted) // 过滤软删除记录（可选）
                .FirstOrDefaultAsync();

            return license;
        }

        
        /// <summary>
        /// 处理法人逻辑（更新或新建）
        /// </summary>
        private async Task<LegalPerson> ProcessLegalPersonAsync(BusinessLicenseCreateDto dto)
        {
            // 情况 1：选择现有法人
            if (dto.LegalPersonId.HasValue)
            {
                var existing = await Context.Set<LegalPerson>()
                    .FirstOrDefaultAsync(lp => lp.Id == dto.LegalPersonId.Value);

                if (existing == null)
                    throw new ArgumentException($"法人 ID {dto.LegalPersonId} 不存在");

                // 如果有提供更新数据，则执行更新
                if (dto.LegalPersonCreate != null)
                {
                    // 检查身份证号是否修改
                    if (existing.IdNumber != dto.LegalPersonCreate.IdNumber)
                    {
                        bool idNumberExists = await Context.Set<LegalPerson>()
                            .AnyAsync(lp => lp.IdNumber == dto.LegalPersonCreate.IdNumber);

                        if (idNumberExists)
                            throw new InvalidOperationException("法人身份证号已存在");
                    }

                    _mapper.Map(dto.LegalPersonCreate, existing);
                    existing.LastModifyTime = DateTime.UtcNow;
                }
                return existing;
            }

            // 情况 2：新建法人
            if (dto.LegalPersonCreate != null)
            {
                bool idNumberExists = await Context.Set<LegalPerson>()
                    .AnyAsync(lp => lp.IdNumber == dto.LegalPersonCreate.IdNumber);

                if (idNumberExists)
                    throw new InvalidOperationException("法人身份证号已存在");

                var newPerson = _mapper.Map<LegalPerson>(dto.LegalPersonCreate);
                Context.Set<LegalPerson>().Add(newPerson);
                return newPerson;
            }

            throw new ArgumentException("无效的法人信息");
        }

        // 修改 ProcessRelatedPersonsAsync 方法中的相关代码
        private async Task ProcessRelatedPersonsAsync(BusinessLicense license, IEnumerable<RelatedPersonOperationDto> persons)
        {
            foreach (var dto in persons)
            {
                RelatedPerson person;

                // 情况 1：选择已有关联人
                if (dto.RelatedPersonId.HasValue)
                {
                    person = await Context.Set<RelatedPerson>()
                        .FirstOrDefaultAsync(p => p.Id == dto.RelatedPersonId.Value);

                    if (person == null)
                        throw new ArgumentException($"关联人 ID {dto.RelatedPersonId} 不存在");

                    // 更新已有数据（如果提供）
                    if (dto.UpdateData != null)
                    {
                        // 检查身份证号是否修改
                        if (person.IdNumber != dto.UpdateData.IdNumber)
                        {
                            bool idNumberExists = await Context.Set<RelatedPerson>()
                                .AnyAsync(rp => rp.IdNumber == dto.UpdateData.IdNumber);

                            if (idNumberExists)
                                throw new InvalidOperationException($"关联人身份证号 {dto.UpdateData.IdNumber} 已存在");
                        }

                        _mapper.Map(dto.UpdateData, person);
                        person.LastModifyTime = DateTime.UtcNow;
                    }
                }
                // 情况 2：新建关联人
                else if (dto.UpdateData != null)
                {
                    bool idNumberExists = await Context.Set<RelatedPerson>()
                        .AnyAsync(rp => rp.IdNumber == dto.UpdateData.IdNumber);

                    if (idNumberExists)
                        throw new InvalidOperationException($"关联人身份证号 {dto.UpdateData.IdNumber} 已存在");

                    person = _mapper.Map<RelatedPerson>(dto.UpdateData);
                    Context.Set<RelatedPerson>().Add(person);
                    await Context.SaveChangesAsync(); // 保存以获取 Id
                }
                else
                {
                    throw new ArgumentException("关联人信息不完整");
                }

                // 创建中间表关联
                license.RelatedPersons.Add(new BusinessLicenseRelatedPerson
                {
                    BusinessLicense = license,
                    RelatedPerson = person
                });
            }
        }

        private bool IsUniqueConstraintViolation(DbUpdateException ex)
        {
            return ex.InnerException is MySqlException mysqlEx &&
                   mysqlEx.ErrorCode == MySqlErrorCode.DuplicateKeyEntry;
        }
    }
}